module ActiveField::Fields

  #NOTE:
  # These classes never get instanciated
  
  class AbstractField
    # 
    # Separator to use when generating DOM id/name/class
    #
    SEP = '__'
    
    class << self
      def build_tag( tag_method, *args )
        ActiveField::Core.build_tag tag_method, *args
      end
      
      def generate_dom_id( record, field_name )
        record_id = record.new_record? ? 'new' : record.id.to_s
        ActiveField::Core.underscore(record.class) + SEP + record_id + SEP + field_name.to_s
      end
      
      def generate_dom_name( record, field_name )
        ActiveField::Core.underscore(record.class) + '[' + field_name.to_s + ']'
      end
      
      def generate_dom_class( record, field_name )
        ActiveField::Core.underscore(record.class) + SEP + field_name.to_s
      end
      
      def edit( record, field_name, options = {} )
        value             = record[field_name]
        dom_name          = generate_dom_name record, field_name
        options[:id]    ||= generate_dom_id record, field_name
        options[:class] ||= generate_dom_class record, field_name
        options[:size]  ||= 30
        build_tag :text_field_tag, dom_name, value, options
      end
      
      def show( record, field_name, options = {} )
        record[field_name]
      end
      
      protected
        def register
          ActiveField::FieldMapper.register_field self
        end
    end
    register
  end
  
  class IntegerField < AbstractField
    class << self
      def edit( record, field_name, options = {} )
        options[:size] ||= 6
        super record, field_name, options
      end
    end
    register
  end
  
  class DecimalField < IntegerField
    class << self
      def edit( record, field_name, options = {} )
        super record, field_name, options
      end
    end
    register
  end
  
  class FloatField < IntegerField
    register
  end
  
  class StringField < AbstractField
    class << self
    end
    register
  end
  
  class TextField < StringField
    class << self
      def edit( record, field_name, options = {} )
        value             = record[field_name]
        dom_name          = options.delete(:name) || generate_dom_name( record, field_name )
        options[:id]    ||= generate_dom_id record, field_name
        options[:class] ||= generate_dom_class record, field_name
        build_tag :text_area_tag, dom_name, value, options
      end
    end
    register
  end
  
  
  class DateField < AbstractField
    #FIXME : when clicking on the month/day in the selectbox in Firefox, it returns to the year.
    class << self
      def edit( record, field_name, options = {}, html_options = {} )
        value  = record[field_name]
        options[:prefix]     ||= generate_dom_name record, field_name
        #html_options[:name]  ||= generate_dom_name record, field_name  # this sets it for all 3 dropdown
        #html_options[:id]    ||= generate_dom_id record, field_name    #
        html_options[:class] ||= generate_dom_class record, field_name
        build_tag :select_date, value, options, html_options
      end
    end
    register
  end
  
  class DatetimeField < AbstractField
    #FIXME : when clicking on the month/day in the selectbox in Firefox, it returns to the year.
    class << self
      def edit( record, field_name, options = {}, html_options = {} )
        value             = record[field_name]
        html_options[:name]  ||= generate_dom_name record, field_name
        html_options[:id]    ||= generate_dom_id record, field_name
        html_options[:class] ||= generate_dom_class record, field_name
        build_tag :select_datetime, value, options, html_options
      end
    end
    register
  end
  
  class ChoiceField < AbstractField
    class << self
      #
      # Allow to fetch choices dynamically
      #
      def get_choices( record, field_name, options )
        choices = options.delete(:choices) || [ ['yes',true], ['no',false] ]
      end
      
      def edit( record, field_name, options = {} )
        options = record.class.fields[field_name].merge options
        
        #choices = options.delete(:choices) || [ ['yes',true], ['no',false] ]
        choices = get_choices record, field_name, options
        value   = record[field_name]
        name    = options.delete(:name) || generate_dom_name( record, field_name )
        
        option_tags = ActiveField::Core.options_for_select choices, value
        
        options[:id]    ||= generate_dom_id record, field_name
        options[:class] ||= generate_dom_class record, field_name
        build_tag :select_tag, name, option_tags, options
      end
    end
    register
  end
  
  
  class BooleanField < ChoiceField
    class << self
      def get_choices( record, field_name, options )
        choices = options.delete(:choices) || [ ['yes',true], ['no',false] ]
      end
      
      def edit( record, field_name, options = {} )
        options = record.class.fields[field_name].merge options
        puts "options = " + options.inspect
        
        choices = get_choices record, field_name, options
        value   = record[field_name]
        name    = options.delete(:name) || generate_dom_name( record, field_name )
        
        options[:id]    ||= generate_dom_id record, field_name
        options[:class] ||= generate_dom_class record, field_name
        build_tag :radio_group_with_label, name, choices, value
      end
    end
    register
  end
  
  # TODO : create fields for all basic database types
  # 
  # Rails types : binary, boolean, date, datetime, decimal, float, integer, string, text
  # 
  # http://dizzy.co.uk/ruby_on_rails/cheatsheets/rails-migrations
  #
  # http://wiki.rubyonrails.org/rails/pages/UsingMigrations
  # http://api.rubyonrails.com/classes/ActiveRecord/Migration.html
  # http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html
  
end
